package com.slz3.business.module.goodsManagement.baseGoods.sync;

import com.slz3.business.frame.module.DomainEntity;
import com.slz3.business.frame.module.Repositorys;
import com.slz3.business.frame.redis.RedisKey;
import com.slz3.business.frame.steward.Steward;
import com.slz3.business.frame.util.RedisClient;
import com.slz3.business.frame.util.VE;
import com.slz3.business.module.goodsManagement.gooBaseGoodsAttribute.domain.GooBaseGoodsAttribute;
import com.slz3.business.module.goodsManagement.gooBaseGoodsAttribute.steward.GooBaseGoodsAttributeConverter;
import com.slz3.business.module.goodsManagement.gooBaseGoodsAttributeValue.domain.GooBaseGoodsAttributeValue;
import com.slz3.business.module.goodsManagement.gooBaseGoodsAttributeValue.steward.GooBaseGoodsAttributeValueConverter;
import com.slz3.business.module.goodsManagement.gooBaseGoodsSpecification.domain.GooBaseGoodsSpecification;
import com.slz3.business.module.goodsManagement.gooBaseGoodsSpecification.steward.GooBaseGoodsSpecificationConverter;
import com.slz3.business.module.goodsManagement.gooBaseGoodsSpecificationValue.domain.GooBaseGoodsSpecificationValue;
import com.slz3.business.module.goodsManagement.gooBaseGoodsSpecificationValue.steward.GooBaseGoodsSpecificationValueConverter;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

public class BaseGoodsPGToRedisSync {

    /**
     * sync GooBaseGoodsAttribute
     * sync GooBaseGoodsAttributeValue
     * sync GooBaseGoodsSpecification
     * sync GooBaseGoodsSpecificationValue
     */
    public static void sync(RedisTemplate redisTemplate, List<DomainEntity> validAll, List<UUID> pkGooBaseGoodsList) {

        // param

        // TODO all update
//        List<UUID> gooBaseGoodsUUID = validAll.stream().map(DomainEntity::getUuid).collect(toList());

        // check

        if (VE.isEmpty(pkGooBaseGoodsList)) {
            return;
        }

        // data

        List<GooBaseGoodsAttribute> attrList = Repositorys.gooBaseGoodsAttribute.findByFkGooBaseGoods(pkGooBaseGoodsList);
        Map<UUID, List<GooBaseGoodsAttribute>> attrListMap = GooBaseGoodsAttributeConverter.listToListMap(attrList);

        List<GooBaseGoodsAttributeValue> attrValList = Repositorys.gooBaseGoodsAttributeValue.findByUpperList(
                attrList.stream().map(GooBaseGoodsAttribute::getUuid).collect(toList())
        );
        Map<UUID, List<GooBaseGoodsAttributeValue>> attrValListMap = GooBaseGoodsAttributeValueConverter.listToListMap(attrValList);

        List<GooBaseGoodsSpecification> specList = Repositorys.gooBaseGoodsSpecification.findByFkGooBaseGoods(pkGooBaseGoodsList);
        Map<UUID, List<GooBaseGoodsSpecification>> specListMap = GooBaseGoodsSpecificationConverter.listToListMap(specList);

        List<GooBaseGoodsSpecificationValue> specValList = Repositorys.gooBaseGoodsSpecificationValue.findByUpperList(
                specList.stream().map(GooBaseGoodsSpecification::getUuid).collect(toList())
        );
        Map<UUID, List<GooBaseGoodsSpecificationValue>> specValListMap = GooBaseGoodsSpecificationValueConverter.listToListMap(specValList);

        // RKE: redis key-entity
        Map<String, String> attrRKEMap = attrList.stream()
                .filter(item -> item.getUuid() != null)
                .collect(toMap(item -> RedisKey.gooBaseGoodsAttribute.entity(item.getUuid()), t -> Steward.toJson(t)));

        Map<String, String> attrValRKEMap = attrValList.stream()
                .filter(item -> item.getUuid() != null)
                .collect(toMap(item -> RedisKey.gooBaseGoodsAttributeValue.entity(item.getUuid()), t -> Steward.toJson(t)));

        Map<String, String> specRKEMap = specList.stream()
                .filter(item -> item.getUuid() != null)
                .collect(toMap(item -> RedisKey.gooBaseGoodsSpecification.entity(item.getUuid()), t -> Steward.toJson(t)));

        Map<String, String> specValRKEMap = specValList.stream()
                .filter(item -> item.getUuid() != null)
                .collect(toMap(item -> RedisKey.gooBaseGoodsSpecificationValue.entity(item.getUuid()), t -> Steward.toJson(t)));

        // RUL: redis relation/key uuid list || Set
        Map<String, List<String>> attrRULMap = GooBaseGoodsAttributeConverter.mapToRULMap(attrListMap);
        Map<String, List<String>> attrValRULMap = GooBaseGoodsAttributeValueConverter.mapToRULMap(attrValListMap);
        Map<String, List<String>> specRULMap = GooBaseGoodsSpecificationConverter.mapToRULMap(specListMap);
        Map<String, List<String>> specValRULMap = GooBaseGoodsSpecificationValueConverter.mapToRULMap(specValListMap);

        // set data to redis
        // entity
        RedisClient.redisTemplate.opsForValue().multiSet(attrRKEMap);
        RedisClient.redisTemplate.opsForValue().multiSet(attrValRKEMap);
        RedisClient.redisTemplate.opsForValue().multiSet(specRKEMap);
        RedisClient.redisTemplate.opsForValue().multiSet(specValRKEMap);
        // uuid set
        RedisClient.redisTemplate.opsForSet().add(RedisKey.gooBaseGoodsAttribute.uuidSet(), attrList.stream().map(it -> it.getUuid().toString()).toArray());
        RedisClient.redisTemplate.opsForSet().add(RedisKey.gooBaseGoodsAttributeValue.uuidSet(), attrValList.stream().map(it -> it.getUuid().toString()).toArray());
        RedisClient.redisTemplate.opsForSet().add(RedisKey.gooBaseGoodsSpecification.uuidSet(), specList.stream().map(it -> it.getUuid().toString()).toArray());
        RedisClient.redisTemplate.opsForSet().add(RedisKey.gooBaseGoodsSpecificationValue.uuidSet(), specValList.stream().map(it -> it.getUuid().toString()).toArray());
        // upper - uuid list - set
        attrRULMap.entrySet().forEach(item ->
                RedisClient.redisTemplate.opsForSet().add(item.getKey(), item.getValue().toArray())
        );
        attrValRULMap.entrySet().forEach(item ->
                RedisClient.redisTemplate.opsForSet().add(item.getKey(), item.getValue().toArray())
        );
        specRULMap.entrySet().forEach(item ->
                RedisClient.redisTemplate.opsForSet().add(item.getKey(), item.getValue().toArray())
        );
        specValRULMap.entrySet().forEach(item ->
                RedisClient.redisTemplate.opsForSet().add(item.getKey(), item.getValue().toArray())
        );

    }

}
